use crate::{ApiError, ApiResult, ToError};
use data_encoding::BASE64;
use rsa::pkcs8::{EncodePrivateKey, EncodePublicKey, LineEnding};
use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
use std::path::Path;
use std::sync::LazyLock;

/// 私钥
static PRIVATE_KEY: LazyLock<RsaPrivateKey> = LazyLock::new(|| {
    let mut rng = rand::thread_rng();
    let bits = 2048;
    RsaPrivateKey::new(&mut rng, bits).expect("生成私钥失败")
});

/// 公钥
static PUBLIC_KEY: LazyLock<RsaPublicKey> = LazyLock::new(|| {
    let private_key: &RsaPrivateKey = &PRIVATE_KEY;
    RsaPublicKey::from(private_key)
});

/// 生成公钥和私钥
pub fn generate() -> ApiResult<(RsaPrivateKey, RsaPublicKey)> {
    let mut rng = rand::thread_rng();
    let bits = 2048;
    let private_key =
        RsaPrivateKey::new(&mut rng, bits).to_err(|| ApiError::Biz("生成rsa私钥错误".into()))?;
    let public_key = RsaPublicKey::from(&private_key);
    Ok((private_key, public_key))
}

/// rsa加密
pub fn encrypt<D: AsRef<[u8]>>(data: D) -> ApiResult<String> {
    let pub_key = &PUBLIC_KEY;
    let mut rng = rand::thread_rng();
    let enc_data = pub_key
        .encrypt(&mut rng, Pkcs1v15Encrypt, data.as_ref())
        .to_err(|| ApiError::Biz("rsa加密错误".into()))?;
    Ok(BASE64.encode(enc_data.as_slice()))
}

/// rsa解密
pub fn decrypt<D: AsRef<[u8]>>(data: D) -> ApiResult<String> {
    let data = BASE64
        .decode(data.as_ref())
        .to_err(|| ApiError::Biz("rsa解密错误".into()))?;
    let priv_key = &PRIVATE_KEY;
    let vec = priv_key
        .decrypt(Pkcs1v15Encrypt, &data)
        .to_err(|| ApiError::Biz("rsa解密错误".into()))?;
    String::from_utf8(vec).to_err(|| ApiError::Biz("rsa解密错误".into()))
}

/// rsa解密
pub fn decrypt_vec<D: AsRef<[u8]>>(data: D) -> ApiResult<Vec<u8>> {
    let data = BASE64
        .decode(data.as_ref())
        .to_err(|| ApiError::Biz("rsa解密错误".into()))?;
    let priv_key = &PRIVATE_KEY;
    priv_key
        .decrypt(Pkcs1v15Encrypt, &data)
        .to_err(|| ApiError::Biz("rsa解密错误".into()))
}

/// 将私钥保存到本地
pub fn write_pkcs8_pem_file<P: AsRef<Path>>(priv_key: &RsaPrivateKey, path: P) -> ApiResult<()> {
    // let priv_key = &PRIVATE_KEY;
    priv_key
        .write_pkcs8_pem_file(path.as_ref(), LineEnding::default())
        .to_err(|| ApiError::Biz("保存rsa私钥错误".into()))
}

/// 私钥的字符串
pub fn to_pkcs8_pem(priv_key: &RsaPrivateKey) -> ApiResult<String> {
    // let priv_key = &PRIVATE_KEY;
    priv_key
        .to_pkcs8_pem(LineEnding::default())
        .map(|pem| pem.as_str().to_owned())
        .to_err(|| ApiError::Biz("保存rsa私钥错误".into()))
}

/// 将公钥保存到本地
pub fn write_public_key_pem_file<P: AsRef<Path>>(pub_key: &RsaPublicKey, path: P) -> ApiResult<()> {
    // let pub_key = &PUBLIC_KEY;

    pub_key
        .write_public_key_pem_file(path.as_ref(), LineEnding::default())
        .to_err(|| ApiError::Biz("保存rsa公钥错误".into()))
}


/// 公钥的字符串
pub fn to_public_key_pem<P: AsRef<Path>>(pub_key: &RsaPublicKey) -> ApiResult<String> {
    // let pub_key = &PUBLIC_KEY;

    pub_key
        .to_public_key_pem(LineEnding::default())
        .to_err(|| ApiError::Biz("保存rsa公钥错误".into()))
}

